import 'package:amap_flutter_location/amap_flutter_location.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:tld_amapsearch/tld_amapSearch.dart';
import 'location_model.dart';
import 'map_base.dart';
import 'dart:async';
import 'package:amap_flutter_map/amap_flutter_map.dart';
import 'package:amap_flutter_base/amap_flutter_base.dart';
import 'package:amap_flutter_location/amap_location_option.dart';
import 'dart:io';

class AMapUtil extends MapBase {
  /// 地图通信中心
  AMapController? _mapController;

  /// 地图创建成功回调
  MapCreatedSuccess? _onMapCallback;

  /// 定位结果监听
  StreamSubscription<Map<String, Object>>? _locationListener;

  /// 定位
  AMapFlutterLocation _locationPlugin = AMapFlutterLocation();

  /// 标记点，需要先设置一个空的map赋值给AMapWidget的markers，否则后续无法添加marker
  final Map<String, Marker> _markers = <String, Marker>{};

  /// 轨迹线，需要先设置一个空的map赋值给AMapWidget
  Map<String, Polyline> _polylines = <String, Polyline>{};

  /// 保存当前轨迹线，以便修改
  Polyline? _polyline;

  /// 保存当前位置的MarkerId，以便修改
  String? _currentMarkerId;

  /// 防止重复创建
  bool _hasInitMarker = false;

  /// 当前定位标记点
  Marker? _marker;

  LatLng markerPosition = const LatLng(39.909187, 116.397451); // 默认位置

  /// 隐私权政策是否包含高德开平隐私权政策
  bool? hasContains;

  /// 隐私权政策是否弹窗展示告知用户
  bool? hasShow;

  /// 隐私权政策是否已经取得用户同意
  bool? hasAgree;

  /// 地图keys
  AMapApiKey? amapApiKeys;

  /// 定位成功回调
  LocationModelCallback? locationModelCallback;
  LocationCallback? locationCallback;

  @override
  void initMapConfig(String androidKey, String iosKey,
      {bool? hasContains,
      bool? hasShow,
      bool? hasAgree,
      LatLngCommon? latlng,
      LocationCallback? locationCallback,
      LocationModelCallback? locationModelCallback}) async {
    print('📍 --- initMapConfig --- 1');
    this.hasContains = hasContains;
    this.hasShow = hasShow;
    this.hasAgree = hasAgree;
    this.locationCallback = locationCallback;
    this.locationModelCallback = locationModelCallback;
    if (latlng != null) {
      markerPosition = LatLng(latlng.latitude, latlng.longitude);
    }

    print('📍 --- initMapConfig --- 2');
    amapApiKeys = AMapApiKey(androidKey: androidKey, iosKey: iosKey);

    /// 定位相关配置
    /// 设置是否已经包含高德隐私政策并弹窗展示显示用户查看，如果未包含或者没有弹窗展示，高德定位SDK将不会工作
    /// 设置是否已经取得用户同意，如果未取得用户同意，高德定位SDK将不会工作
    AMapFlutterLocation.updatePrivacyShow(hasContains ?? true, hasShow ?? true);
    AMapFlutterLocation.updatePrivacyAgree(hasAgree ?? true);

    print('📍 --- initMapConfig --- 3');

    /// 设置Android和iOS的apiKey
    AMapFlutterLocation.setApiKey(androidKey, iosKey);
    print('📍 --- initMapConfig --- 4');

    // iOS 获取native精度类型
    if (Platform.isIOS) {
      requestAccuracyAuthorization();
    }
    // 注册定位结果监听
    _locationListener = _locationPlugin
        .onLocationChanged()
        .listen((Map<String, Object> result) {
      print('📍 --- 监听到位置 --- $result');
      if (locationRepeat != true) {
        stopLocation();
      }

      if (locationModelCallback != null) {
        locationModelCallback(LocationModel.fromMap(result));
      }

      Object? latitudeObj = result['latitude'];
      Object? longitudeObj = result['longitude'];

      double latitude;
      double longitude;
      if (latitudeObj != null && longitudeObj != null) {
        if (latitudeObj is double && longitudeObj is double) {
          latitude = latitudeObj;
          longitude = longitudeObj;
        } else {
          latitude = double.parse(latitudeObj as String);
          longitude = double.parse(longitudeObj as String);
        }

        markerPosition = LatLng(latitude, longitude);
        LatLngCommon position = LatLngCommon(latitude, longitude);
        print('📍📍📍 --- 当前位置【AMAP】--- $position');

        if (locationCallback != null) {
          locationCallback(position);
        }
      }
    });
    print('📍 --- 注册定位结果监听   ${_locationListener}');
  }

  @override
  Widget buildMap(BuildContext context, MapCreatedSuccess? onMapCallback,
      {double? width, double? height, bool enableGestureRecognizers = false}) {
    this._onMapCallback = onMapCallback;

    mapHeight = height;
    mapWidth = width;

    AMapPrivacyStatement amapPrivacyStatement = AMapPrivacyStatement(
        hasContains: this.hasContains ?? true,
        hasShow: this.hasShow ?? true,
        hasAgree: this.hasAgree ?? true);

    /// 使用默认属性创建一个地图
    final AMapWidget map = AMapWidget(
      apiKey: amapApiKeys,
      mapType: MapType.night,
      onMapCreated: _onMapCreated,
      markers: Set<Marker>.of(_markers.values),
      polylines: Set<Polyline>.of(_polylines.values),
      scaleEnabled: scaleEnabled,
      compassEnabled: compassEnabled,
      rotateGesturesEnabled: gesturesEnabled,
      scrollGesturesEnabled: gesturesEnabled,
      tiltGesturesEnabled: gesturesEnabled,
      zoomGesturesEnabled: gesturesEnabled,
      privacyStatement: amapPrivacyStatement,

      /// 地图应该使用哪些手势。
      ///
      /// 其他手势识别器可能会在指针上与地图竞争
      /// 事件，例如，如果地图在 [ListView] 内，则 [ListView] 将要处理
      /// 垂直拖动。 地图将声明被任何人识别的手势
      /// 此列表中的识别器。
      ///
      /// 当这个集合为空时，地图将只处理手势的指针事件
      /// 未被任何其他手势识别器声明。
      gestureRecognizers: enableGestureRecognizers
          ? {
              Factory<OneSequenceGestureRecognizer>(
                () => EagerGestureRecognizer(),
              )
            }
          : const <Factory<OneSequenceGestureRecognizer>>{},
      initialCameraPosition: CameraPosition(
        // 初始化中心点
        //中心点
        target: markerPosition,
        // //缩放级别
        zoom: zoom,
        // //俯仰角0°~45°（垂直与地图时为0）
        // tilt: 30,
        // //偏航角 0~360° (正北方为0)
        // bearing: 0
      ),
      // 限制显示区域
      // limitBounds: LatLngBounds(
      //     southwest: LatLng(39.83309, 116.290176),
      //     northeast: LatLng(39.99951, 116.501663)),

      // 地图类型：satellite - 卫星地图
      // mapType: MapType.satellite,
    );

    return Container(
      height: mapHeight ?? MediaQuery.of(context).size.height,
      width: mapWidth ?? MediaQuery.of(context).size.width,
      // height: 300,
      // width: MediaQuery.of(context).size.width,
      child: map,
    );
  }

  /// 地图创建成功
  void _onMapCreated(dynamic) {
    this._mapController = dynamic;
    if (_onMapCallback != null) {
      _onMapCallback!(1);
    }
    getApprovalNumber(); // 获取审图号
  }

  /// 生成截图
  Future<Uint8List?> takeSnapshot() async {
    return await this._mapController?.takeSnapshot();
  }

  @override
  void startLocation({bool? repeat}) {
    print('开始定位');

    if (_locationListener == null) {
      return;
    }

    locationRepeat = repeat;

    if (_locationListener?.isPaused == true) {
      _locationListener?.resume();
      print('_locationListener --- resume');
    }

    ///开始定位之前设置定位参数
    _setLocationOption();

    /// 开始定位
    _locationPlugin.startLocation();
  }

  @override
  void stopLocation() {
    print('停止定位');
    _locationListener?.pause();
    print('_locationListener --- pause');

    // 停止定位
    _locationPlugin.stopLocation();
  }

  @override
  void destroy() {
    print('📍 销毁定位');
    _locationListener?.cancel();
    print('_locationListener --- cancel');
    _locationListener = null;
    // 销毁定位
    _locationPlugin.destroy();
  }

  @override
  void movePosition(LatLngCommon? latlng, bool animated) {
    LatLng newPosition;
    if (latlng == null) {
      newPosition = markerPosition;
    } else {
      newPosition = LatLng(latlng.latitude, latlng.longitude);
    }

    // 移动地图中心点
    _mapController?.moveCamera(
      CameraUpdate.newCameraPosition(
        CameraPosition(
            //中心点
            target: newPosition,
            //缩放级别
            zoom: zoom,
            //俯仰角0°~45°（垂直与地图时为0）
            tilt: tilt,
            //偏航角 0~360° (正北方为0)
            bearing: bearing),
      ),
      animated: animated,
    );
  }

  @override
  Future<bool>? initCurrMarker(
      BuildContext context,
      bool showInfoWindow,
      String infoWindowTitle,
      String imageAsset,
      void Function(String value)? onTap) async {
    print('1 --- 位置更新 --- $_hasInitMarker');
    if (_hasInitMarker) {
      return false;
    }
    BitmapDescriptor? _markerIcon = await _createMarkerImageFromAsset(
        context, imageAsset); //'images/marker_icon.png'
    _marker = Marker(
      position: markerPosition,
      // 使用AssetImage
      icon: _markerIcon!,
      infoWindowEnable: showInfoWindow, // 是否显示气泡
      infoWindow: InfoWindow(title: infoWindowTitle), // 气泡显示内容
      onTap: onTap,
    );

    print('2 --- 位置更新 --- ${_marker!.id}');
    // 需要调用setState才能显示
    _currentMarkerId = _marker!.id;
    _markers[_marker!.id] = _marker!;
    _hasInitMarker = true;

    return true;
  }

  @override
  void updateCurrMarker() {
    print('3 --- 位置更新 --- $_currentMarkerId');
    // 修改当前标记点位置
    if (_currentMarkerId != null) {
      Marker marker = _markers[_currentMarkerId]!;
      _markers[_currentMarkerId!] = marker.copyWith(
        positionParam: markerPosition,
      );
    }
  }

  @override
  Future addMarker(
    BuildContext context,
    LatLngCommon latlng,
    bool showInfoWindow,
    String infoWindowTitle,
    String imageAsset,
    void Function(String p1)? onTap, {
    double rotation = 0.0,
    void Function(String)? callbackMarkId,
  }) async {
    LatLng newPoint = LatLng(latlng.latitude, latlng.longitude);

    BitmapDescriptor? markerIcon =
        await _createMarkerImageFromAsset(context, imageAsset);

    final Marker marker = Marker(
      position: newPoint,
      icon: markerIcon!,
      infoWindowEnable: showInfoWindow, // 是否显示气泡
      infoWindow: InfoWindow(title: infoWindowTitle), // 气泡显示内容
      onTap: onTap,
      rotation: rotation,
    );
    if (callbackMarkId != null) {
      callbackMarkId(marker.id);
    }

    // 需要调用setState才能显示
    _markers[marker.id] = marker;
  }

  @override
  void initLine(BuildContext context, List<LatLngCommon> points, double width,
      void Function(String p1) onTap) {
    List<LatLng> newPoints = getLatLngPoints(points);
    _polyline = Polyline(
        color: polylineColor, //colors[++colorsIndex % colors.length],
        width: width,
        points: newPoints,
        onTap: onTap,
        capType: CapType.round, // 线头类型 圆形头
        joinType: JoinType.round // 连接点类型 圆角
        );

    // 需要调用setState才能显示
    _polylines[_polyline!.id] = _polyline!;
  }

  /// 获取iOS native的accuracyAuthorization类型
  void requestAccuracyAuthorization() async {
    AMapAccuracyAuthorization currentAccuracyAuthorization =
        await _locationPlugin.getSystemAccuracyAuthorization();
    if (currentAccuracyAuthorization ==
        AMapAccuracyAuthorization.AMapAccuracyAuthorizationFullAccuracy) {
      print("📍 --- 精确定位类型");
    } else if (currentAccuracyAuthorization ==
        AMapAccuracyAuthorization.AMapAccuracyAuthorizationReducedAccuracy) {
      print("📍 --- 模糊定位类型");
    } else {
      print("📍 --- 未知定位类型");
    }
  }

  /// 转换坐标数组
  List<LatLng> getLatLngPoints(List<LatLngCommon> points) {
    List<LatLng> newPoints = <LatLng>[];
    //   List newList2 = listArr2.map((value){
    //   return value*2;
    // });
    // 将数据LatLngCommon修改为LatLng
    newPoints =
        points.map((point) => LatLng(point.latitude, point.longitude)).toList();
    return newPoints;
  }

  /// 创建自定义Marker Icon
  Future<BitmapDescriptor?> _createMarkerImageFromAsset(
      BuildContext context, String imageAsset) async {
    final ImageConfiguration imageConfiguration = createLocalImageConfiguration(
        context); //(context, size: Size.square(48))
    BitmapDescriptor? _markerIcon =
        await BitmapDescriptor.fromAssetImage(imageConfiguration, imageAsset);
    return _markerIcon;
  }

  /// 获取审图号
  void getApprovalNumber() async {
    //普通地图审图号
    String? mapContentApprovalNumber =
        await _mapController?.getMapContentApprovalNumber();
    //卫星地图审图号
    String? satelliteImageApprovalNumber =
        await _mapController?.getSatelliteImageApprovalNumber();
  }

  /// 设置定位参数
  void _setLocationOption() {
    AMapLocationOption locationOption = new AMapLocationOption();

    ///是否单次定位
    locationOption.onceLocation = false;

    ///是否需要返回逆地理信息
    locationOption.needAddress = true;

    ///逆地理信息的语言类型
    locationOption.geoLanguage = GeoLanguage.DEFAULT;

    locationOption.desiredLocationAccuracyAuthorizationMode =
        AMapLocationAccuracyAuthorizationMode.ReduceAccuracy;

    locationOption.fullAccuracyPurposeKey = "AMapLocationScene";

    ///设置Android端连续定位的定位间隔
    locationOption.locationInterval = 2000;

    ///设置Android端的定位模式<br>
    ///可选值：<br>
    ///<li>[AMapLocationMode.Battery_Saving]</li>
    ///<li>[AMapLocationMode.Device_Sensors]</li>
    ///<li>[AMapLocationMode.Hight_Accuracy]</li>
    locationOption.locationMode = AMapLocationMode.Hight_Accuracy;

    ///设置iOS端的定位最小更新距离<br>
    locationOption.distanceFilter = -1;

    ///设置iOS端期望的定位精度
    /// 可选值：<br>
    /// <li>[DesiredAccuracy.Best] 最高精度</li>
    /// <li>[DesiredAccuracy.BestForNavigation] 适用于导航场景的高精度 </li>
    /// <li>[DesiredAccuracy.NearestTenMeters] 10米 </li>
    /// <li>[DesiredAccuracy.Kilometer] 1000米</li>
    /// <li>[DesiredAccuracy.ThreeKilometers] 3000米</li>
    locationOption.desiredAccuracy = DesiredAccuracy.Best;

    ///设置iOS端是否允许系统暂停定位
    locationOption.pausesLocationUpdatesAutomatically = false;

    ///将定位参数设置给定位插件
    _locationPlugin.setLocationOption(locationOption);

    print('📍 --- 设置定位参数');
  }

  @override
  Future<String> getGeocodeAddress(LatLngCommon latlng) async {
    print('高德地图逆地理编码申请');
    String? address;
    await TldAmapSearch.reGeocoding(
        longitude: latlng.longitude,
        latitude: latlng.latitude,
        back: (code, data) {
          address = data.regeocodeAddress?.formattedAddress;
          print('code:$code 逆地理编码:${data.regeocodeAddress?.formattedAddress}');
        });
    print('end');
    if (address == null) {
      await Future.delayed(Duration(milliseconds: 50));
    }
    return address ?? '';
  }

  @override
  void clearMarkers({String? id}) {
    if (id != null) {
      _markers.remove(id);
    } else {
      _markers.clear();
    }
  }

  @override
  MapClassType getMapType() {
    return MapClassType.gaode;
  }
}
